package service.rocksea.com.serviceapp;



/**
 * 蓝牙或WIFI接收数据缓冲区
 * 蓝牙端口一个包的数据会分多次发送,中间会有数据丢失情况发生
 *
 * */
public class ReceiveBuffer {
    public byte[] m_bytes = null;
    public int m_recievelength = 0;//接受的长度
    public int m_start = 0;//起始位置

    public ReceiveBuffer() {
        m_bytes = new byte[4096];
        m_recievelength = 0;
        m_start = 0;
    }

    public void clear() {
        for (int i = 0; i < m_bytes.length; i++) {
            m_bytes[i] = (byte) 0x00;
        }
        m_recievelength = 0;
        m_start = 0;
    }

    public boolean recieve(byte[] bytes, int len) {
        if (bytes == null || len == 0)
            return false;

        if ((m_recievelength + len) > 4096) {
            clear();
            return false;
        }
        try {
            System.arraycopy(bytes, 0, m_bytes, m_recievelength, len);
        } catch (ArrayStoreException ex) {

            // 发生存储转换，部分成功的数据会被复制过去

            System.out.println("拷贝发生异常：数据转换错误，无法存储。");

        } catch (IndexOutOfBoundsException | NullPointerException ex) {
            //IndexOutOfBoundsException -- if copying would cause access of data outside array bounds.
            //ArrayStoreException -- if an element in the src array could not be stored into the dest array because of a type mismatch.
            //NullPointerException
        }
        m_recievelength += len;
        return true;
    }

    public UDPPacket checkSumPackage(int start) {
        m_start = nextStartPos(m_start);//查找命令起始符号0xAB
        if (m_start == -1)
            return null;

        if ((m_recievelength - m_start) < 22)//最小GPS包22字节,登录回复包38字节
            return null;

        // 数据未接收齐
        short udplen = (short) ((0x000000FF & m_bytes[m_start + 18]) | ((0x000000FF & m_bytes[m_start + 19]) << 8));
        udplen += (short) 22;
        if (udplen > (short) 534 || udplen < (short) 0) {
            m_start++;
            return checkSumPackage(m_start);
        }
        if ((int) udplen > (m_recievelength - m_start))
            return null;

        // 帧尾字符不对
        if (m_bytes[m_start + udplen - 1] != (byte) 0xAB) {
            m_start++;
            return checkSumPackage(m_start);
        }

        // 校验和不对2
        if (checkSumBuffer(udplen, m_start) != 0) {
            m_start++;
            return checkSumPackage(m_start);
        }
        // 有完整数据包了，提取该数据包并返回
        return new UDPPacket().initWithBytes(m_bytes, udplen, m_start);
    }
    private int nextStartPos(int start) {
        int pos = -1;
        for (int i = start; i < m_recievelength; i++) {
            if (m_bytes[i] == (byte) 0xAB) {
                pos = i;
                break;
            }
        }
        return pos;
    }

    private byte checkSumBuffer(int udplen, int start) {
        //校验和(低位在前，高位在后)
        //buffer是指向需要校验数据缓冲区的指针，size是需要检验数据的总长度(字节为单位)
        byte cksum = 0;
        for (int i = start; i < start + udplen; i++) {
            cksum += m_bytes[i];
        }
        return cksum;
    }
}